﻿define(['durandal/system', 'config', 'services/model', 'services/logger', 'services/breeze.partial-entities'],
    function (system, config, model, logger, partialMapper) {
        
        var entityQuery = breeze.EntityQuery,
            manager = configureBreezeMgr();

        function configureBreezeMgr() {    
            breeze.NamingConvention.camelCase.setAsDefault();
            var mgr = new breeze.EntityManager(config.remoteServiceName);
            model.configureMetadataStore(mgr.metadataStore);
            return mgr;
        }

        var getShowCaseCars = function (carObservable) {
            var query = entityQuery.from('GetShowCaseCars');
            return manager.executeQuery(query)
                          .then(querySucceeded)
                          .fail(queryFailed);

            function querySucceeded(data) {
                if (carObservable !== null) {
                    carObservable(data.results);
                }
            };
        };

        var getCarsBySize = function (carObservable,apiMethod, size) {
            var query = entityQuery.from(apiMethod)
                                   .take(size);
            return manager.executeQuery(query)
                .then(querySucceeded)
                .fail(queryFailed);

            function querySucceeded(data) {
                //var list = partialMapper.mapDtosToEntities(manager, data.results, 'Car', 'id');
                var list = data.results;
                if (carObservable !== null) {
                    carObservable(list);
                }

                log('Retrieved [' + apiMethod + '] from remote data source',
                    data, true);
            }
        };

        var getCarsByPage = function (carObservable, apiMethod,currentPage, pageSize, totalPages, totalRecords, forceRemote) {
                //if (!forceRemote) {
                //    var featuredcars = getLocal('Car', null);
                //    if (featuredcars.length > 0) {
                //        carObservable(featuredcars);
                //        return Q.resolve();
                //    }
                //}
            var query;
            if (pageSize) {
                query = entityQuery.from(apiMethod)
                                   .skip(currentPage() * pageSize())
                                   .take(pageSize())
                                   .inlineCount(true);
            }
            else {
                query = entityQuery.from(apiMethod);
            }
            return manager.executeQuery(query)
                .then(querySucceeded)
                .fail(queryFailed);

            function querySucceeded(data) {
                //var list = partialMapper.mapDtosToEntities(manager, data.results, 'Car', 'id');
                var list = data.results;
                if (carObservable !== null) {
                    carObservable(list);
                    if (totalPages !== null) {
                        totalPages(Math.ceil(data.inlineCount / pageSize()));
                    }
                    if (totalRecords !== null) {
                        totalRecords(data.inlineCount);
                    }
                }
                
                log('Retrieved [' + apiMethod + '] from remote data source',
                    data, true);
            }
        };
     
        var getCarBySessionId = function (id, carObservable) {
            return manager.fetchEntityByKey('Car', id, true)
                .then(fetchSucceeded)
                .fail(queryFailed);

            function fetchSucceeded(data) {
                var c = data.entity;
                return c.isPartial() ? getFullObject(c) : carObservable(c);
            }

            function getFullObject(c) {
                return entityQuery.fromEntities(c)
                    .using(manager).execute()
                    .then(querySucceeded)
                    .fail(queryFailed);
            }

            function querySucceeded(data) {
                var car = data.results[0];
                car.isPartial(false);
                return carObservable(car);
            }
        };

        function getLocal(resource, ordering) {
            var query;
            if (ordering !== null) {
                query = entityQuery.from(resource)
                    .orderBy(ordering);
            } else {
                query = entityQuery.from(resource);
            }
            return manager.executeQueryLocally(query);
        }

        
        var getPrimeData = function () {

            //var promise = Q.all([getFeaturedCars(null, 1, null, null, null, true)]);
            //return promise;
        };
        
        function queryFailed(error) {
            var msg = 'Error retreiving data. ' + error.message;
            logError(msg, error);
            throw error;
        }

        function log(msg, data, showToast) {
            logger.log(msg, data, system.getModuleId(datacontext), showToast);
        }

        function logError(msg, error) {
            logger.logError(msg, error, system.getModuleId(datacontext), true);
        }


        var datacontext = {
            getPrimeData: getPrimeData,
            getShowCaseCars: getShowCaseCars,
            getCarsBySize: getCarsBySize,
            getCarsByPage: getCarsByPage,
            getCarBySessionId: getCarBySessionId
        };
        return datacontext;
    });